# -*- coding: utf-8 -*-
from datetime import datetime, timedelta

from google.appengine.ext import db

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from appengine_django.models import BaseModel as _BaseModel
#from appengine_django.models import BaseModel

import logging

from util import get_this_year, get_this_month, get_today
from util.emc import is_available_time, is_available_equipment

class BaseModel(_BaseModel):
    id = db.IntegerProperty()

    def put(self):
        _BaseModel.put(self)
        self.id = self.key().id()
        _BaseModel.put(self)

    @classmethod
    def get_using_id(self, id):
        str_query = 'SELECT * FROM ' + self.kind() + ' WHERE id = :1'
        query = db.GqlQuery(str_query, id)
        return query.fetch(10)[0]

    @property
    def get_absolute_url(self):
        detail_name = self.__class__.__name__ + '_' + 'detail'
        return HttpResponseRedirect(reverse(detail_name.lower(), args=(self.id,)))

#####
days = ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
class TimeSlot(BaseModel):
    day = db.StringProperty(choices=days, default=days[0])
    start_time = db.TimeProperty()
    end_time = db.TimeProperty()

class User(BaseModel):
    first_name = db.StringProperty(required=True)
    second_name = db.StringProperty(required=True)
    email = db.EmailProperty()
    mobilephone = db.PhoneNumberProperty()
    phone = db.PhoneNumberProperty()
    address = db.PostalAddressProperty()

class StaffManager(object):
    @staticmethod
    def is_exist(first_name):
        query = Staff.gql('WHERE first_name=:first_name', first_name=first_name)
        staffs = query.fetch(1000)
        return True if staffs else False

class Staff(User):
    def __unicode__(self):
        return '%s' % self.first_name

##
YEAR = get_this_year()
YEARS = list(range(YEAR-5, YEAR+5))

class ETeacher(User):
    pay = db.IntegerProperty()
    year = db.IntegerProperty(choices=YEARS, default=YEAR)
    not_available_times = db.ListProperty(db.Key)

    @property
    def timeslots(self):
        return db.get(self.not_available_times)

    def __unicode__(self):
        return '%s' % self.first_name


## Class School
SCHOOL_TYPE = ['P', 'M', 'GM', 'H', 'GH', 'U', 'etc']
PROVINCE_TYPE = ['KN', 'KB','CN', 'CB', 'US']

class SchoolManager(object):
    @staticmethod
    def is_exist(year, name, stage, local):
        query = School.gql('WHERE year=:year AND name=:name AND stage=:stage AND local=:local',
                    year=int(year), name=name, stage=stage, local=local)
        schools = query.fetch(1000)
        return True if schools else False

class School(BaseModel):
    year = db.IntegerProperty(choices=YEARS, default=YEAR)
    name = db.StringProperty(verbose_name='name*', required=True)
    en_name = db.StringProperty(verbose_name='en name*',required=True)
    stage = db.StringProperty(choices=SCHOOL_TYPE, default=SCHOOL_TYPE[0])
    province = db.StringProperty(choices=PROVINCE_TYPE, default=PROVINCE_TYPE[0])
    local = db.StringProperty(verbose_name='local*', required=True)
    phone = db.TextProperty()
    address = db.StringProperty()
    postcode = db.StringProperty()
    IPs = db.TextProperty()
    coordinator = db.ReferenceProperty(Staff)
    principal = db.StringProperty()
    vice_principal = db.StringProperty()
    log = db.TextProperty()
    last_updated = db.DateTimeProperty(auto_now=True)

    @property
    def ip(self):
        return self.IPs[-1]

    def __unicode__(self):
        return '%s_%s' % (self.name, self.stage)

CURRENT_TYPE = ['Woring', 'Not-Working']

class KTeacher(User):
    school = db.ReferenceProperty(School)
    current = db.StringProperty(choices=CURRENT_TYPE, default=CURRENT_TYPE[0])
    def __unicode__(self):
        return '%s%s' % (self.first_name, self.second_name)


class ETeacherHistory(BaseModel):
    eteacher = db.ReferenceProperty(ETeacher)
    school = db.ReferenceProperty(School)
    year = db.IntegerProperty(choices=YEARS, default=YEAR)
    log = db.TextProperty()
    last_updated = db.DateTimeProperty(auto_now=True)

## Invoice
MONTH = range(1, 13)
SENT_EMAIL = ('Not yet', 'Sent')
INVOICE_STATUS = ('Waiting', 'Confirmed', 'Not received', 'Receive')

class Invoice(BaseModel):
    school = db.ReferenceProperty(School)
    year = db.IntegerProperty(default=YEAR)
    month = db.IntegerProperty(choices=MONTH, default=MONTH[0])
    sent_email = db.StringProperty(choices=SENT_EMAIL, default=SENT_EMAIL[0])
    status = db.StringProperty(choices=INVOICE_STATUS, default=INVOICE_STATUS[0])
    start_date = db.DateProperty()
    end_date = db.DateProperty()
    uint_price = db.IntegerProperty(default=70000)
    count_classes = db.IntegerProperty(default=1)
    total_price =  db.IntegerProperty()

# Booth
booth_number = range(1, 40)
equipment_type = ['Computer', 'Polycom', '4NB', 'Skype', 'Lifesize', 'ETC']
class Booth(BaseModel):
    number = db.IntegerProperty(
                verbose_name='Booth Number',
                choices=booth_number,
                default=booth_number[0])
    equipment = db.StringProperty(
                verbose_name='장비',
                choices=equipment_type,
                default=equipment_type[0])

    def is_available(self, oneclass):
        for aclass in self.classes:
            if not is_available_time(aclass, oneclass):
                return 'Cannot Assign'
        if not is_available_equipment(oneclass, self):
            return 'Invalid equipment'
        return ''
    def __unicode__(self):
        return '%s' % (self.number)

## Issue
COUNTERPLAN = ('None', 'Check', 'Observe', 'Request to call', 'Called', 'Fixed')
class Issue(BaseModel):
    time = db.DateTimeProperty() #auto_now=True
    school = db.ReferenceProperty(School, collection_name='issues')
    booth = db.ReferenceProperty(Booth, collection_name='issues')
    note = db.TextProperty()
    process = db.StringProperty(choices=COUNTERPLAN, default=COUNTERPLAN[0])

## class time
grades = [1, 2, 3, 4, 5, 6]
DAYS = ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
CLASS_TYPE = ['Regular', 'Extra', 'Training']
TEXTBOOK_TYPE = ['SiSa', 'MiRae', 'ChunJae(Ham)', 'KukJung', 'Etc']
class ClassProperty(BaseModel):
    day = db.StringProperty(choices=DAYS, default=DAYS[0])
    grade = db.IntegerProperty(choices=grades, default=grades[0])
    textbook = db.StringProperty(choices=TEXTBOOK_TYPE, default=TEXTBOOK_TYPE[0])
    equipment = db.StringProperty(
                verbose_name='장비',
                choices=equipment_type,
                default=equipment_type[0])
    start_time = db.TimeProperty()
    end_time = db.TimeProperty()
    eteacher = db.ReferenceProperty(ETeacher, collection_name='class_properties')
    kteacher = db.ReferenceProperty(KTeacher)
    school = db.ReferenceProperty(School)
    type = db.StringProperty(choices=CLASS_TYPE, default=CLASS_TYPE[0])

    def __unicode__(self):
        return '%s-%s' % (self.school.name, self.grade)

    def change_start_time(self):
        for oneclass in self.classes:
            oneclass.start_time = self.start_time
            oneclass.put()

    def change_end_time(self):
        for oneclass in self.classes:
            oneclass.ebd_time = self.end_time
            oneclass.put()

    def delte_classes(self):
        db.delete(self.classes)

## class
STATUSES = ['Prepare', 'Done', 'Cancel', 'Delete', 'Cancel & Pay']
class OneClass(BaseModel):
    date = db.DateProperty()
    ## ClassProperty
    day = db.StringProperty(choices=DAYS, default=DAYS[0])
    grade = db.IntegerProperty(choices=grades, default=grades[0])
    start_time = db.TimeProperty()
    end_time = db.TimeProperty()
    school = db.ReferenceProperty(School)
    kteacher = db.ReferenceProperty(KTeacher)
    eteacher = db.ReferenceProperty(ETeacher)
    textbook = db.StringProperty(choices=TEXTBOOK_TYPE, default=TEXTBOOK_TYPE[0])
    equipment = db.StringProperty(
                verbose_name='장비',
                choices=equipment_type,
                default=equipment_type[0])
    type = db.StringProperty(choices=CLASS_TYPE, default=CLASS_TYPE[0])
    ## end
    status = db.StringProperty(choices=STATUSES, default=STATUSES[0])
    lesson = db.StringProperty()
    booth = db.ReferenceProperty(Booth, collection_name='classes')
    classproperty = db.ReferenceProperty(ClassProperty, collection_name='classes')

    @property
    def name(self):
        return str(self.start_time) +   '-' + \
                str(self.end_time) + ' ' + \
                self.school_name

    @property
    def school_id(self):
        if self.classproperty:
            return self.classproperty.school.id
        return self.school.id

    @property
    def school_name(self):
        if self.classproperty:
            return self.classproperty.school.name
        return self.school.name

#    @property
#    def end_time(self):
#        if self.changed_end_time:
#            return self.changed_end_time
#        else:
#            return self.classproperty.end_time



## Invoice
MONTH = range(1, 13)
#SENT_EMAIL = ('Not yet', 'Sent')
INVOICE_STATUS = ('Unpaid', 'Paid', 'Overdue', 'Check', 'Conform', 'Sent email')
INVOICE_TYPE = ('Regular', 'After', 'Vacation', 'Resource', 'ETC')
THIS_YEAR = get_this_year()
THIS_MONTH = get_this_month()
TODAY = get_today()
DUE_DATE = TODAY + timedelta(15)

class TempInvoiceManager(object):
    @staticmethod
    def is_exist(school, year, month, type):
        query = TempInvoice.gql('WHERE school=:school AND year=:year AND month=:month AND type=:type',
                    school=school.key(), year=int(year), month=int(month), type=type)
        invoices = query.fetch(1000)
        return True if invoices else False

class TempInvoice(BaseModel):
#    school = db.StringProperty()
    no = db.IntegerProperty()
    school = db.ReferenceProperty(School)
    year = db.IntegerProperty(default=YEAR)
    month = db.IntegerProperty(choices=MONTH, default=THIS_MONTH)
    type = db.StringProperty(choices=INVOICE_TYPE, default=INVOICE_TYPE[0])
    invoiced_date = db.DateProperty(default=TODAY)
    due_date = db.DateProperty(default=DUE_DATE)
    start_date = db.DateProperty(required=True)
    end_date = db.DateProperty(required=True)
    uint_price = db.IntegerProperty(default=70000)
    count_classes = db.IntegerProperty(default=1)
    total_price =  db.IntegerProperty()
    pay_date = db.DateProperty()
    status = db.StringProperty(choices=INVOICE_STATUS, default=INVOICE_STATUS[0])
    note = db.TextProperty()